﻿using System;
using System.IO.Ports;
using NDK.Utils;
using System.Net.Sockets;
using System.Threading;
using BZ.Logger;

namespace NDK.Module.Model
{
    public enum LightControlerChanel
    {
        SA = 0,
        SB,
        SC,
        SD
    };

    public class RseeLightController
    {
        private static log4net.ILog m_Logger = log4net.LogManager.GetLogger("RseeLightController");
        #region 变量

        SerialPort _port = new SerialPort();
        string _COM;
        AsySockets asySocket = new AsySockets();
        private string ReceiveData = string.Empty;
        Socket _mySocket = NetUtils.CreateTcpSocket();
        string ip;
        public string Ip
        {
            get { return ip; }
            set { ip = value; }
        }
        int _iport = 8234;
        public int Iport
        {
            get { return _iport; }
            set { _iport = value; }
        }

        public Socket Mysocket
        {
            get { return _mySocket; }
            set { _mySocket = value; }
        }

        string _name;
        LightControlerChanel _chanel;
        Int16 _ID;
        Int16 _value;
        string _project;
        #endregion

        #region 属性
        public SerialPort Port
        {
            get { return _port; }
            set { _port = value; }
        }

        public string COM
        {
            get { return _COM; }
            set { _COM = value; }
        }

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private string _type;
        public string Type
        {
            get { return _type; }
            set { _type = value; }
        }
        public LightControlerChanel Chanel
        {
            get { return _chanel; }
            set { _chanel = value; }
        }

        public Int16 ID
        {
            get { return _ID; }
            set { _ID = value; }
        }
        public string Project
        {
            get { return _project; }
            set { _project = value; }
        }

        public Int16 Value
        {
            get { return _value; }
            set { _value = value; }
        }
        #endregion

        #region 方法

        /// <summary>
        /// 打开(指定串口号)
        /// </summary>
        public bool Open(string com)
        {
            COM = com;
            try
            {
                if (com.Contains("."))
                {
                    asySocket.ConnectServer(com, Iport);
                    asySocket.ReceiveDataCompleteEvent += new AsySockets.ReceiveDataCompleteHandler(_onRecieveData1);
                    return true;
                }
                _port.PortName = com;
                if (_port.IsOpen) return false;

                string comParam = "19200,0,8,1,\r";
                string[] arg = comParam.Trim().Split(',');

                _port.BaudRate = int.Parse(arg[0].Trim());
                _port.Parity = (Parity)int.Parse(arg[1].Trim());
                _port.DataBits = int.Parse(arg[2].Trim());
                _port.StopBits = (StopBits)int.Parse(arg[3].Trim());
                _port.Handshake = Handshake.None;
                _port.DataReceived += new SerialDataReceivedEventHandler(_port_DataReceived);

#if DEBUG
                _port.ReadTimeout = 500; // DEBUG时 禁止COM端口读写超时
                _port.WriteTimeout = -1;
#else
                _port.ReadTimeout = 15000;// RELEASE 时COM端口读写超时为5秒
                _port.WriteTimeout = 15000;
#endif

                _port.Open(); // 打开端口   
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception("Light initialize failed");
            }
        }


        /// <summary>
        /// 关闭
        /// </summary>
        public void Close()
        {
            //lock (_port)
            {
                NetUtils.Close(Mysocket);
                // _port.Close();
            }
        }

        public void SetLightValue()
        {
            //环光3
            //Open();
            WriteData((LightControlerChanel)Chanel, Value);
            //Close();
        }
        public void SetLightValue(int value)
        {
            //环光3
            //Open();
            WriteData((LightControlerChanel)Chanel, value);
            //Close();
        }

        /// <summary>
        /// 读取字符串
        /// </summary>
        /// <returns>返回值：接受到数据</returns>
        public string Read()
        {
            try
            {
                string strTempValue = string.Empty;
                if (!_port.IsOpen) return "";
                strTempValue = _port.ReadExisting();
                return strTempValue;
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        /// 写入指令
        /// </summary>
        /// <param name="sendV">指令</param>
        public void WriteData(string sendV)
        {
            _port.PortName = "com" + COM;
            //if (_port.IsOpen) return true;
            string comParam = "19200,0,8,1,\r";
            string[] arg = comParam.Trim().Split(',');

            _port.BaudRate = int.Parse(arg[0].Trim());
            _port.Parity = (Parity)int.Parse(arg[1].Trim());
            _port.DataBits = int.Parse(arg[2].Trim());
            _port.StopBits = (StopBits)int.Parse(arg[3].Trim());
            if (!_port.IsOpen) return;
            _port.WriteLine(sendV);
        }

        private static readonly object _lock = new object();
        /*
         函数名：WriteData
         传入参数：
         Channel: 光源通道(从1开始)
         nLight：光源亮度(0-255有效)
         */
        public void WriteData(LightControlerChanel channel, int nLight)
        {
            lock (_lock)
            {
                //if (!_port.IsOpen && !_mySocket.Connected)
                bool? isConnected = false;
                isConnected = asySocket.isSocketConnected();
                if (!_port.IsOpen && isConnected != true)
                {
                    return;
                }

                string strChannel = null;
                switch (channel)
                {
                    case LightControlerChanel.SA:
                        strChannel = "SA";
                        break;
                    case LightControlerChanel.SB:
                        strChannel = "SB";
                        break;
                    case LightControlerChanel.SC:
                        strChannel = "SC";
                        break;
                    case LightControlerChanel.SD:
                        strChannel = "SD";
                        break;
                    default:
                        break;
                }

                string strSend = null;
                if (nLight > 255)
                {
                    strSend = strChannel + "0255#";
                }
                else if (nLight < 0)
                {
                    strSend = strChannel + "0000#";
                }
                else
                {
                    if ((nLight / 100) > 0)
                    {
                        strSend = strChannel + string.Format("0{0}#", nLight);
                    }
                    else if ((nLight / 10) > 0)
                    {
                        strSend = strChannel + string.Format("00{0}#", nLight);
                    }
                    else
                    {
                        strSend = strChannel + string.Format("000{0}#", nLight);
                    }
                }

                int RepeatTimes = 0;
                if (COM.Contains("."))
                {
                ReSend:
                    asySocket.SendData(strSend);
                    //NetUtils.SendMsg(_mySocket, strSend);
                    RepeatTimes++;
                    //接收光源反馈值
                    Thread.Sleep(10);
                    bool isLightReceiveTimeOut = false;
                    DateTime dt = DateTime.Now;
                    while (ReceiveData == string.Empty || !strChannel.Contains(ReceiveData))
                    {
                        if ((DateTime.Now - dt).TotalMilliseconds >= 5)
                        {
                            isLightReceiveTimeOut = true;
                            break;
                        }
                    }

                    if (isLightReceiveTimeOut)
                    {
                        if (RepeatTimes <= 5)
                            goto ReSend;
                        else
                        {
                            Common.AppendUiLog.Log("接收光源控制器响应超时", LogType.Error);
                            m_Logger.Error("Receive Light FeedBack TimeOut");
                        }
                    }
                    ReceiveData = string.Empty;
                }
                else
                {
                ReSend1:
                    _port.WriteLine(strSend);
                    RepeatTimes++;
                    //接收光源反馈值
                    Thread.Sleep(10);
                    bool isLightReceiveTimeOut = false;
                    DateTime dt = DateTime.Now;
                    while (ReceiveData == string.Empty || !strChannel.Contains(ReceiveData))
                    {
                        if ((DateTime.Now - dt).TotalMilliseconds >= 5)
                        {
                            isLightReceiveTimeOut = true;
                            break;
                        }
                    }

                    if (isLightReceiveTimeOut)
                    {
                        if (RepeatTimes <= 5)
                            goto ReSend1;
                        else
                        {
                            Common.AppendUiLog.Log("接收光源控制器响应超时", LogType.Error);
                            m_Logger.Error("Receive Light FeedBack TimeOut");
                        }
                    }
                    ReceiveData = string.Empty;
                }
            }
        }
        #endregion


        /// <summary>
        /// 关闭所有光源
        /// </summary>
        public void CloseAllLight()
        {
            WriteData(LightControlerChanel.SA, 0);
            WriteData(LightControlerChanel.SB, 0);
            WriteData(LightControlerChanel.SC, 0);
            WriteData(LightControlerChanel.SD, 0);
        }
        #region 事件
        /// <summary>
        /// 串口数据接收事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string strReceiced = this.Read();

            try
            {
                if (strReceiced == string.Empty) { return; }
                strReceiced = strReceiced.Replace("\0", "");
                ReceiveData = strReceiced;
            }
            catch (Exception ex)
            {
            }
        }
        void _onRecieveData1(string strReceiced)
        {
            try
            {
                if (strReceiced == null) { return; }
                strReceiced = strReceiced.Replace("\0", "");
                ReceiveData = strReceiced;
            }
            catch (Exception ex)
            {
            }
        }
        #endregion
    }
}

